/**
 * PrimeFaces TabView Widget
 */
PrimeFaces.widget.TabView = function(cfg) {
    this.cfg = cfg;
    this.id = this.cfg.id;
    this.jqId = PrimeFaces.escapeClientId(this.id);
    this.jq = $(this.jqId);
    this.navContainer = this.jq.children('.ui-tabs-nav');
    this.panelContainer = this.jq.children('.ui-tabs-panels');
    this.stateHolder = $(this.jqId + '_activeIndex');
    this.cfg.selected = parseInt(this.stateHolder.val());
    this.onshowHandlers = [];
    
    this.bindEvents();
	
    //Cache initial active tab
    if(this.cfg.dynamic && this.cfg.cache) {
        this.markAsLoaded(this.panelContainer.children().eq(this.cfg.selected));
    }
    
    this.jq.data('widget', this);
    
    this.postConstruct();
}

PrimeFaces.extend(PrimeFaces.widget.TabView, PrimeFaces.widget.BaseWidget);

PrimeFaces.widget.TabView.prototype.bindEvents = function() {
    var _self = this;
    
    //Tab header events
    this.navContainer.children('li')
            .bind('mouseover.tabview', function(e) {
                var element = $(this);
                if(!element.hasClass('ui-state-disabled')) {
                    element.addClass('ui-state-hover');
                }
            })
            .bind('mouseout.tabview', function(e) {
                var element = $(this);
                if(!element.hasClass('ui-state-disabled')) {
                    element.removeClass('ui-state-hover');
                }
            })
            .bind('click.tabview', function(e) {
                var element = $(this);
                
                if($(e.target).is(':not(.ui-icon-close)')) {
                    var index = element.index();

                    if(!element.hasClass('ui-state-disabled') && index != _self.cfg.selected) {
                        _self.select(index);
                    }
                }
                
                e.preventDefault();
            });
            
    //Closable tabs
    this.navContainer.find('li .ui-icon-close')
        .bind('click.tabview', function(e) {
            _self.remove($(this).parent().index());
            
            e.preventDefault();
        });
}

PrimeFaces.widget.TabView.prototype.bindEventsForOne = function(index) {
    var _self = this;
    
    //Tab header events
    this.navContainer.children('li').eq(index)
            .bind('mouseover.tabview', function(e) {
                var element = $(this);
                if(!element.hasClass('ui-state-disabled')) {
                    element.addClass('ui-state-hover');
                }
            })
            .bind('mouseout.tabview', function(e) {
                var element = $(this);
                if(!element.hasClass('ui-state-disabled')) {
                    element.removeClass('ui-state-hover');
                }
            })
            .bind('click.tabview', function(e) {
                var element = $(this);
                
                if($(e.target).is(':not(.ui-icon-close)')) {
                    var index = element.index();

                    if(!element.hasClass('ui-state-disabled') && index != _self.cfg.selected) {
                        _self.select(index);
                    }
                }
                
                e.preventDefault();
            });
            
    //Closable tabs
    this.navContainer.children('li').eq(index).children('.ui-icon-close')
        .bind('click.tabview', function(e) {
            _self.remove($(this).parent().index());
            
            e.preventDefault();
        });
}

/**
 * Selects an inactive tab given index
 */
PrimeFaces.widget.TabView.prototype.select = function(index) {
    //Call user onTabChange callback
    if(this.cfg.onTabChange) {
        var result = this.cfg.onTabChange.call(this, index);
        if(result == false)
            return false;
    }
    
    var newPanel = this.panelContainer.children().eq(index),
    shouldLoad = this.cfg.dynamic && !this.isLoaded(newPanel);
    //update state
    this.stateHolder.val(index);
    this.cfg.selected = index;
    if(shouldLoad) {
        this.loadDynamicTab(newPanel);
    }
    else {
        this.show(newPanel);
        this.fireTabChangeEvent(newPanel);
    }
    return true;
}

PrimeFaces.widget.TabView.prototype.show = function(newPanel) {
    var headers = this.navContainer.children(),
    oldHeader = headers.filter('.ui-state-active'),
    newHeader = headers.eq(newPanel.index()),
    oldPanel = this.panelContainer.children('.ui-tabs-panel:visible'),
    _self = this;
    
    //aria
    oldPanel.attr('aria-hidden', true);
    oldHeader.attr('aria-expanded', false);
    newPanel.attr('aria-hidden', false);
    newHeader.attr('aria-expanded', true);
    
    if(this.cfg.effect) {
            oldPanel.hide(this.cfg.effect.name, null, this.cfg.effect.duration, function() {
            oldHeader.removeClass('ui-state-focus ui-tabs-selected ui-state-active');
            
            newHeader.addClass('ui-state-focus ui-tabs-selected ui-state-active');
            newPanel.show(_self.cfg.effect.name, null, _self.cfg.effect.duration, function() {
                _self.postTabShow(newPanel);
            });
        });
    }
    else {
        oldHeader.removeClass('ui-state-focus ui-tabs-selected ui-state-active');
        oldPanel.hide();
        
        newHeader.addClass('ui-state-focus ui-tabs-selected ui-state-active');
        newPanel.show();
        
        this.postTabShow(newPanel);
    }
}

/**
 * Loads tab contents with ajax
 */
PrimeFaces.widget.TabView.prototype.loadDynamicTab = function(newPanel) {
    var _self = this,
    options = {
        source: this.id,
        process: this.id,
        update: this.id
    },
    tabindex = newPanel.index();

    options.onsuccess = function(responseXML) {
        var xmlDoc = $(responseXML.documentElement),
        updates = xmlDoc.find("update");

        for(var i=0; i < updates.length; i++) {
            var update = updates.eq(i),
            id = update.attr('id'),
            content = update.text();

            if(id == _self.id){
                newPanel.html(content);

                if(_self.cfg.cache) {
                    _self.markAsLoaded(newPanel);
                }
            }
            else {
                PrimeFaces.ajax.AjaxUtils.updateElement.call(this, id, content);
            }
        }
        
        PrimeFaces.ajax.AjaxUtils.handleResponse.call(this, xmlDoc);

        return true;
    };
    
    options.oncomplete = function() {
        _self.show(newPanel);
        
        if(_self.cfg.onDynamicTabComplete) {
        	_self.cfg.onDynamicTabComplete.call(this, tabindex);
        }
    };


    var params = {};
    params[this.id + '_contentLoad'] = true;
    params[this.id + '_newTab'] = newPanel.attr('id');
    params[this.id + '_tabindex'] = tabindex;

    options.params = params;

    if(this.hasBehavior('tabChange')) {
        var tabChangeBehavior = this.cfg.behaviors['tabChange'];
        
        tabChangeBehavior.call(this, newPanel, options);
    }
    else {
        PrimeFaces.ajax.AjaxRequest(options);
    }
}

/**
 * Removes a tab with given index
 */
PrimeFaces.widget.TabView.prototype.remove = function(index) {    
    var header = this.navContainer.children().eq(index),
    panel = this.panelContainer.children().eq(index);
    
    var visible = jQuery(header.children('.ui-icon-modify')).is(':visible');
    
    if(visible) {
    	if(this.cfg.onTabModifyClose) {
    		this.cfg.onTabModifyClose.call(this, index);
        } else {
        	var tabModifyCloseTip = 'Are you sure remove the tab?';
        	if (this.cfg.tabModifyCloseTip) {
        		tabModifyCloseTip = this.cfg.tabModifyCloseTip;
        	}
        	if (confirm(tabModifyCloseTip)) {
        		this.removeSilence(index);
        	}
        }
    } else {
    	this.removeSilence(index);
    }
}

PrimeFaces.widget.TabView.prototype.removeSilence = function(index) {    
    var header = this.navContainer.children().eq(index),
    panel = this.panelContainer.children().eq(index);
    
    this.fireTabCloseEvent(panel);
    
    header.remove();
    panel.remove();
    
    //active next tab if active tab is removed
    if(index == this.cfg.selected) {
        var newIndex = this.cfg.selected == this.getLength() ? this.cfg.selected - 1: this.cfg.selected;
        this.select(newIndex);
    }
}

PrimeFaces.widget.TabView.prototype.getLength = function() {
    return this.navContainer.children().length;
}

PrimeFaces.widget.TabView.prototype.getActiveIndex = function() {
    return this.cfg.selected;
}

PrimeFaces.widget.TabView.prototype.fireTabChangeEvent = function(panel) {
    var _self = this;
    
    if(this.hasBehavior('tabChange')) {
        var tabChangeBehavior = this.cfg.behaviors['tabChange'],
        ext = {
            params: {}
        };
        ext.params[this.id + '_newTab'] = panel.attr('id');
        ext.params[this.id + '_tabindex'] = panel.index();

        tabChangeBehavior.call(this, panel, ext);
    }
}

PrimeFaces.widget.TabView.prototype.fireTabCloseEvent = function(panel) {    
    if(this.hasBehavior('tabClose')) {
        var tabCloseBehavior = this.cfg.behaviors['tabClose'],
        ext = {
            params: {}
        };
        ext.params[this.id + '_closeTab'] = panel.attr('id')
        ext.params[this.id + '_tabindex'] = panel.index();

        tabCloseBehavior.call(this, null, ext);
    }
}

PrimeFaces.widget.TabView.prototype.hasBehavior = function(event) {
    if(this.cfg.behaviors) {
        return this.cfg.behaviors[event] != undefined;
    }
    
    return false;
}

PrimeFaces.widget.TabView.prototype.markAsLoaded = function(panel) {
    panel.data('loaded', true);
}

PrimeFaces.widget.TabView.prototype.isLoaded = function(panel) {
    return panel.data('loaded') == true;
}

PrimeFaces.widget.TabView.prototype.disable = function(index) {
    this.navContainer.children().eq(index).addClass('ui-state-disabled');
}

PrimeFaces.widget.TabView.prototype.enable = function(index) {
    this.navContainer.children().eq(index).removeClass('ui-state-disabled');
}

PrimeFaces.widget.TabView.prototype.get = function(tabindex) {
	if(!tabindex){
		tabindex = this.getActiveIndex();
	}
	
	return this.navContainer.children().eq(tabindex);
}

PrimeFaces.widget.TabView.prototype.add = function(tabindex, args) {
	var _self = this,
    options = {
        source: this.id,
        process: this.id,
        update: this.id
    };
	var tabNavStr = "<li class='ui-state-default ui-corner-top'>" +
			"<span class='ui-icon ui-icon-bullet ui-icon-modify' style='display:none;'></span>" +
			"<a href='#main-tabSet:" + args.tabId + "'>" + args.tabLable + "</a>";
	
	if (args.tabClosable) {
		tabNavStr = tabNavStr + "<span class='ui-icon ui-icon-close'></span>";
	}
	
	tabNavStr = tabNavStr + "</li>";
	
	var tabNavObj = $(tabNavStr),
	tabPanelObj = $("<div id='main-tabSet:" + args.tabId + "' class='ui-tabs-panel ui-widget-content ui-corner-bottom portal-mainView-tab-content' style='display: none;'></div>");
	if (args.tabContentSrc) {
		tabPanelObj.append("<iframe class='portal-mainView-tab-content-iframe' scrolling='no' frameborder='no' border='0' allowtransparency='true' src='"+args.tabContentSrc+"'></iframe>");
	}
	
	if(!tabindex){
		tabindex = this.navContainer.children().length;
		this.navContainer.append(tabNavObj);
		this.panelContainer.append(tabPanelObj);
	} else {
		this.navContainer.children().eq(tabindex).before(tabNavObj);
		this.panelContainer.children().eq(tabindex).before(tabPanelObj);
	}
	
	this.bindEventsForOne(tabindex);
	
	this.stateHolder.val(tabindex);
    this.cfg.selected = tabindex;
    
    var newPanel = this.panelContainer.children().eq(tabindex);
	if (args.tabContentSrc) {
		this.show(newPanel);
        this.fireTabChangeEvent(newPanel);
	} else {
		this.loadDynamicTab(newPanel);
	}
}

PrimeFaces.widget.TabView.prototype.isModified = function(tabindex, flag) {
	var tabNavModify = this.navContainer.children().eq(tabindex).children('.ui-icon-modify');
	if(flag){
		tabNavModify.show();
	} else {
		tabNavModify.hide();
	}
}
PrimeFaces.widget.TabView.prototype.addOnshowHandler = function(fn) {
    this.onshowHandlers.push(fn);
}

PrimeFaces.widget.TabView.prototype.postTabShow = function(newPanel) {    
    //execute user defined callback
    if(this.cfg.onTabShow) {
        this.cfg.onTabShow.call(this, newPanel);
    }
    
    //execute onshowHandlers and remove successful ones
    this.onshowHandlers = $.grep(this.onshowHandlers, function(fn) {
		return !fn.call();
	});
}
